Skip to content

feat(telemetry): add a live, enriched analytics dashboard#446

Merged
HugoRCD merged 3 commits into
mainfrom
feat/telemetry-live-dashboard
Jul 24, 2026
Merged

feat(telemetry): add a live, enriched analytics dashboard#446
HugoRCD merged 3 commits into
mainfrom
feat/telemetry-live-dashboard

Conversation

@HugoRCD

@HugoRCD HugoRCD commented Jul 23, 2026

Copy link
Copy Markdown
Owner

Summary

  • New live-refreshing dashboard (5s poll, pauses when the run detail slide-over is open or the tab is hidden) with animated KPI cards and a manual pause toggle.
  • Richer breakdowns: AI agent usage, CI vs local + provider split, Node/tool/OS version distribution, error codes, a duration histogram, and an hourly/daily activity chart — all backed by new SQL aggregations (mock-mode aware, so the same code path serves the dashboard, GET /api/telemetry/stats, and the telemetry-stats MCP tool).
  • Daily/hourly activity buckets are now zero-filled across the full selected range instead of only including days with events, so the chart always renders a fixed-width timeline (and its tooltip reliably targets a bar instead of one edge-to-edge bar with a degenerate domain).
  • Collects env.os and env.arch on every run event (nullable, backward compatible with older clients) — new @evlog/telemetry fields, DB columns, and migration.
  • Custom Nucleo icon collection (i-nucleo-*) exported from the local Nucleo library, replacing Lucide icons across the dashboard; adds a light/dark color mode toggle.

Test plan

  • pnpm run lint, pnpm run typecheck, pnpm run test all pass at the repo root
  • Manually verified /api/telemetry/stats returns fully zero-filled buckets for 24h/7d/30d ranges
  • Manual visual pass on the deployed dashboard (light + dark mode, mobile width)

Summary by CodeRabbit

  • New Features
    • Added operating system platform and CPU architecture to telemetry run events and ingest.
    • Expanded the dashboard with new visualizations and cards (agents, CI/local, versions, error codes, duration histogram) plus hourly/daily activity support.
    • Enhanced live experience with a live feed and animated statistics (including reduced-motion behavior).
  • Bug Fixes
    • Improved empty/zero-state rendering and ensured activity/bucket charts show stable, complete ranges; maintained compatibility with older events that omit OS/architecture.
  • Tests
    • Updated mock-data and ingest test coverage for the extended stats and new environment fields.

@vercel

vercel Bot commented Jul 23, 2026

Copy link
Copy Markdown
Contributor

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
evlog-telemetry Ready Ready Preview, Comment Jul 23, 2026 11:02pm
2 Skipped Deployments
Project Deployment Actions Updated (UTC)
evlog-docs Skipped Skipped Jul 23, 2026 11:02pm
just-use-evlog Skipped Skipped Jul 23, 2026 11:02pm

Request Review

@github-actions

Copy link
Copy Markdown
Contributor

Thank you for following the naming conventions! 🙏

@coderabbitai

coderabbitai Bot commented Jul 23, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

Telemetry ingestion now captures nullable OS and architecture metadata. The telemetry API and mock data expose expanded activity, environment, error, version, and duration statistics, while the dashboard adds live polling, a live feed, new breakdown cards, charts, animations, and Nucleo icon support.

Changes

Telemetry analytics dashboard

Layer / File(s) Summary
Environment contract and persistence
packages/telemetry/..., apps/telemetry/server/db/..., apps/telemetry/server/utils/store.ts
Environment types, ingestion, enrichment, database schema, storage, and run details now include nullable OS and architecture fields.
Statistics contracts and aggregation
apps/telemetry/shared/..., apps/telemetry/server/utils/telemetry-queries.ts, apps/telemetry/server/utils/mock-data.ts, apps/telemetry/test/mock-data.test.ts
Stats now include zero-filled daily/hourly activity, environment and version breakdowns, error codes, duration histograms, percentiles, and latest-event timestamps.
Live refresh and feed flow
apps/telemetry/app/composables/*, apps/telemetry/app/components/Live*.vue, apps/telemetry/app/pages/index.vue
The dashboard polls stats, table, and feed data with visibility, in-flight, suspension, and toggle guards, and highlights newly received runs.
Analytics cards and dashboard composition
apps/telemetry/app/components/{AgentsBreakdown,CiBreakdown,VersionsCard,ErrorCodesCard,DurationHistogram,BreakdownBars,DailyActivityChart,StatCard}.vue, apps/telemetry/app/pages/index.vue
New cards and charts render agent, CI, platform, version, error, duration, hourly, and numeric statistic data.
Icon, motion, and dashboard styling
apps/telemetry/app/assets/css/main.css, apps/telemetry/app/utils/telemetry-icons.ts, apps/telemetry/scripts/*, apps/telemetry/nuxt.config.ts, apps/telemetry/app/components/*
Nucleo icon assets and mappings replace selected Lucide icons, while dashboard transitions, live flashes, staggered entry effects, and reduced-motion overrides are added.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant LiveIndicator
  participant Dashboard
  participant TelemetryAPI
  participant LiveFeed
  User->>LiveIndicator: toggle live polling
  LiveIndicator->>Dashboard: emit toggle
  Dashboard->>TelemetryAPI: refresh stats, runs, and feed
  TelemetryAPI-->>Dashboard: return aggregates and newest runs
  Dashboard->>LiveFeed: render updated feed
  LiveFeed-->>Dashboard: emit selected run
Loading

Possibly related PRs

  • HugoRCD/evlog#417: Extends the telemetry ingestion environment validation that this change updates with nullable OS and architecture fields.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 73.53% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title is concise and accurately summarizes the main change: a live, enriched telemetry dashboard.
Description check ✅ Passed The description covers the main changes and test plan, though it omits the linked issue and checklist sections from the template.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/telemetry-live-dashboard

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 Biome (2.5.3)
apps/telemetry/app/assets/css/main.css

File contains syntax errors that prevent linting: Line 9: Tailwind-specific syntax is disabled.; Line 14: Tailwind-specific syntax is disabled.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@pkg-pr-new

pkg-pr-new Bot commented Jul 23, 2026

Copy link
Copy Markdown
npm i https://pkg.pr.new/evlog@446
npm i https://pkg.pr.new/@evlog/nuxthub@446
npm i https://pkg.pr.new/@evlog/telemetry@446

commit: 078a245

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 6

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@apps/telemetry/app/composables/useFreshIds.ts`:
- Around line 12-25: Update the rows watcher in useFreshIds so seenIds is pruned
to the currently visible row IDs on each update, while preserving existing IDs
needed to detect newly arrived rows in the current batch. Keep the initialized
handling and freshIds flash behavior unchanged, and ensure seenIds cannot retain
IDs absent from the latest rows.

In `@apps/telemetry/app/composables/useLiveRefresh.ts`:
- Around line 40-48: Update the live-refresh flow around tick() so refresh
failures are observable to its callers despite useFetch/useAsyncData refresh()
resolving while populating .error. Surface the failing fetcher error or a
failure timestamp/status from the composable, and ensure index.vue’s polling and
LiveIndicator consume that signal so repeated failures no longer appear as
“Live”.

In `@apps/telemetry/app/pages/index.vue`:
- Around line 256-257: Remove the HTML comment from the Vue template near the
card layout markup in the index page. If the note is still needed, move it into
the script block using the project’s supported comment style; otherwise delete
it without changing the card layout behavior.

In `@apps/telemetry/app/utils/telemetry-icons.ts`:
- Around line 43-45: Document the exported helpers providerIcon and osLabel in
apps/telemetry/app/utils/telemetry-icons.ts at lines 43-45 and 70-73: add JSDoc
for providerIcon describing its provider icon lookup and i-nucleo-server
fallback, and add JSDoc for osLabel describing its OS label lookup and fallback
behavior.

In `@apps/telemetry/server/db/migrations/postgresql/meta/0001_snapshot.json`:
- Around line 1-5: Remove the generated Drizzle migration metadata artifacts:
delete the snapshot file at
apps/telemetry/server/db/migrations/postgresql/meta/0001_snapshot.json and
remove the corresponding journal entry at
apps/telemetry/server/db/migrations/postgresql/meta/_journal.json lines 11-17.

In `@apps/telemetry/shared/types/telemetry.ts`:
- Around line 75-92: Add concise interface-level JSDoc comments to the exported
ErrorCodeStat and DurationStats interfaces, describing the error-code occurrence
statistics and duration percentile/histogram statistics. Leave their existing
fields and the DurationBucket documentation unchanged.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: e4d481c3-a74d-4b5c-a522-b0373be010a7

📥 Commits

Reviewing files that changed from the base of the PR and between a87ab5d and 078a245.

⛔ Files ignored due to path filters (42)
  • apps/telemetry/app/assets/icons/nucleo/bolt.svg is excluded by !**/*.svg
  • apps/telemetry/app/assets/icons/nucleo/box.svg is excluded by !**/*.svg
  • apps/telemetry/app/assets/icons/nucleo/bug.svg is excluded by !**/*.svg
  • apps/telemetry/app/assets/icons/nucleo/calendar.svg is excluded by !**/*.svg
  • apps/telemetry/app/assets/icons/nucleo/chart-line.svg is excluded by !**/*.svg
  • apps/telemetry/app/assets/icons/nucleo/check.svg is excluded by !**/*.svg
  • apps/telemetry/app/assets/icons/nucleo/chevron-down.svg is excluded by !**/*.svg
  • apps/telemetry/app/assets/icons/nucleo/chevron-up.svg is excluded by !**/*.svg
  • apps/telemetry/app/assets/icons/nucleo/chevrons-expand.svg is excluded by !**/*.svg
  • apps/telemetry/app/assets/icons/nucleo/circle-check.svg is excluded by !**/*.svg
  • apps/telemetry/app/assets/icons/nucleo/circle-info.svg is excluded by !**/*.svg
  • apps/telemetry/app/assets/icons/nucleo/circle-warning.svg is excluded by !**/*.svg
  • apps/telemetry/app/assets/icons/nucleo/clipboard-check.svg is excluded by !**/*.svg
  • apps/telemetry/app/assets/icons/nucleo/code-editor.svg is excluded by !**/*.svg
  • apps/telemetry/app/assets/icons/nucleo/connect.svg is excluded by !**/*.svg
  • apps/telemetry/app/assets/icons/nucleo/copy.svg is excluded by !**/*.svg
  • apps/telemetry/app/assets/icons/nucleo/dial.svg is excluded by !**/*.svg
  • apps/telemetry/app/assets/icons/nucleo/flag.svg is excluded by !**/*.svg
  • apps/telemetry/app/assets/icons/nucleo/gauge.svg is excluded by !**/*.svg
  • apps/telemetry/app/assets/icons/nucleo/inbox.svg is excluded by !**/*.svg
  • apps/telemetry/app/assets/icons/nucleo/key.svg is excluded by !**/*.svg
  • apps/telemetry/app/assets/icons/nucleo/laptop-mobile.svg is excluded by !**/*.svg
  • apps/telemetry/app/assets/icons/nucleo/laptop.svg is excluded by !**/*.svg
  • apps/telemetry/app/assets/icons/nucleo/layers.svg is excluded by !**/*.svg
  • apps/telemetry/app/assets/icons/nucleo/loader.svg is excluded by !**/*.svg
  • apps/telemetry/app/assets/icons/nucleo/log-out.svg is excluded by !**/*.svg
  • apps/telemetry/app/assets/icons/nucleo/pause.svg is excluded by !**/*.svg
  • apps/telemetry/app/assets/icons/nucleo/play.svg is excluded by !**/*.svg
  • apps/telemetry/app/assets/icons/nucleo/plug.svg is excluded by !**/*.svg
  • apps/telemetry/app/assets/icons/nucleo/refresh.svg is excluded by !**/*.svg
  • apps/telemetry/app/assets/icons/nucleo/rocket.svg is excluded by !**/*.svg
  • apps/telemetry/app/assets/icons/nucleo/server.svg is excluded by !**/*.svg
  • apps/telemetry/app/assets/icons/nucleo/sparkle-outline.svg is excluded by !**/*.svg
  • apps/telemetry/app/assets/icons/nucleo/sparkle.svg is excluded by !**/*.svg
  • apps/telemetry/app/assets/icons/nucleo/tags.svg is excluded by !**/*.svg
  • apps/telemetry/app/assets/icons/nucleo/tasks.svg is excluded by !**/*.svg
  • apps/telemetry/app/assets/icons/nucleo/terminal.svg is excluded by !**/*.svg
  • apps/telemetry/app/assets/icons/nucleo/triangle-warning.svg is excluded by !**/*.svg
  • apps/telemetry/app/assets/icons/nucleo/ufo.svg is excluded by !**/*.svg
  • apps/telemetry/app/assets/icons/nucleo/user.svg is excluded by !**/*.svg
  • packages/telemetry/test/__snapshots__/telemetry.test.ts.snap is excluded by !**/*.snap
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (43)
  • .changeset/heavy-planes-shout.md
  • apps/telemetry/app/assets/css/main.css
  • apps/telemetry/app/components/AgentsBreakdown.vue
  • apps/telemetry/app/components/BreakdownBars.vue
  • apps/telemetry/app/components/CiBreakdown.vue
  • apps/telemetry/app/components/CommandsTable.vue
  • apps/telemetry/app/components/DailyActivityChart.vue
  • apps/telemetry/app/components/DurationHistogram.vue
  • apps/telemetry/app/components/EnvironmentBreakdown.vue
  • apps/telemetry/app/components/ErrorCodesCard.vue
  • apps/telemetry/app/components/LiveFeed.vue
  • apps/telemetry/app/components/LiveIndicator.vue
  • apps/telemetry/app/components/McpConnectButton.vue
  • apps/telemetry/app/components/RunDetailPanel.vue
  • apps/telemetry/app/components/RunsTable.vue
  • apps/telemetry/app/components/StatCard.vue
  • apps/telemetry/app/components/VersionsCard.vue
  • apps/telemetry/app/composables/useFreshIds.ts
  • apps/telemetry/app/composables/useLiveRefresh.ts
  • apps/telemetry/app/pages/index.vue
  • apps/telemetry/app/pages/login.vue
  • apps/telemetry/app/utils/telemetry-icons.ts
  • apps/telemetry/nuxt.config.ts
  • apps/telemetry/package.json
  • apps/telemetry/scripts/export-nucleo-icons.mjs
  • apps/telemetry/server/db/migrations/postgresql/0001_legal_goliath.sql
  • apps/telemetry/server/db/migrations/postgresql/meta/0001_snapshot.json
  • apps/telemetry/server/db/migrations/postgresql/meta/_journal.json
  • apps/telemetry/server/db/schema.ts
  • apps/telemetry/server/mcp/tools/telemetry-stats.ts
  • apps/telemetry/server/utils/mock-data.ts
  • apps/telemetry/server/utils/store.ts
  • apps/telemetry/server/utils/telemetry-queries.ts
  • apps/telemetry/shared/types/telemetry.ts
  • apps/telemetry/shared/utils/activity-buckets.ts
  • apps/telemetry/shared/utils/duration-buckets.ts
  • apps/telemetry/test/mock-data.test.ts
  • packages/telemetry/src/disclosure.ts
  • packages/telemetry/src/enrich.ts
  • packages/telemetry/src/ingest.ts
  • packages/telemetry/src/types.ts
  • packages/telemetry/test/enrich.test.ts
  • packages/telemetry/test/ingest.test.ts

Comment thread apps/telemetry/app/composables/useFreshIds.ts
Comment on lines +40 to +48
async function tick() {
if (!active.value || inFlight.value) return
inFlight.value = true
try {
await refresh()
} finally {
inFlight.value = false
}
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🌐 Web query:

Does Nuxt useFetch's refresh() reject the returned promise when the request fails, or does it only populate the error ref?

💡 Result:

The refresh (and its alias execute) function returned by Nuxt's useFetch does not reject the promise when a request fails [1][2]. Instead, it handles errors internally by populating the error ref and updating the status ref to 'error' [3][4][1]. Because the promise does not reject, using await refresh within a try/catch block will not catch HTTP or network errors [1][2]. To handle errors when using useFetch, you should check the error ref after the request completes or use the status ref [1]. If you require the ability to catch errors via a promise rejection, you would typically need to use $fetch directly, though this means losing the built-in reactive state management (data, pending, status, error) provided by useFetch [1][2]. As of July 2026, there have been community discussions and requests for a throwOnError option to allow these composables to reject on failure, but they do not do so by default [2].

Citations:


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== locate files =="
fd -a 'useLiveRefresh\.ts$|index\.vue$' . | sed 's#^\./##'

echo "== git status/stat =="
git status --short
git diff --stat -- packages apps 2>/dev/null || true

echo "== relevant file outlines =="
for f in $(fd 'useLiveRefresh\.ts|index\.vue$' apps/telemetry/app 2>/dev/null); do
  echo "--- $f"
  wc -l "$f"
  ast-grep outline "$f" --view compact || true
done

echo "== useLiveRefresh.ts =="
f="$(fd 'useLiveRefresh\.ts$' apps/telemetry/app | head -n1)"
if [ -n "${f:-}" ]; then
  cat -n "$f"
fi

echo "== index.vue snippets matching refresh/useLiveRefresh =="
for f in $(fd '^index\.vue$' apps/telemetry/app/composables apps/telemetry/app 2>/dev/null); do
  if rg -q 'useLiveRefresh|refresh\(' "$f"; then
    echo "--- $f"
    wc -l "$f"
    rg -n -C 8 'useLiveRefresh|refresh\(|LiveIndicator|lastError|stats\.error|runsData|feedData' "$f" || true
  fi
done

echo "== package versions =="
for f in package.json apps/telemetry/package.json pnpm-lock.yaml package-lock.json yarn.lock; do
  if [ -f "$f" ]; then
    echo "--- $f"
    if [ "$f" = "package.json" ] || [ "$f" = "apps/telemetry/package.json" ]; then
      jq -r '.dependencies.nuxt?, .devDependencies.nuxt?, .packageManager?' "$f" 2>/dev/null || cat "$f"
    else
      rg -n 'nuxt(@|@)|version:.*(nuxt|nestjs|react|vue)|node_modules' "$f" | head -n 80 || true
    fi
  fi
done

Repository: HugoRCD/evlog

Length of output: 20175


Report failed live-refresh outcomes.

tick() waits for refresh() but does not expose failures, and Nuxt’s useFetch/useAsyncData refresh() captures errors in the .error ref rather than rejecting the returned promise. With index.vue polling Promise.all([refreshStats(), refreshRuns(), refreshFeed()]), a repeated fetch failure can leave LiveIndicator showing “Live” while data stops updating. Return/report an error or failure timestamp from this composable, or surface the failing fetcher’s .error/status state at the call site.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/telemetry/app/composables/useLiveRefresh.ts` around lines 40 - 48,
Update the live-refresh flow around tick() so refresh failures are observable to
its callers despite useFetch/useAsyncData refresh() resolving while populating
.error. Surface the failing fetcher error or a failure timestamp/status from the
composable, and ensure index.vue’s polling and LiveIndicator consume that signal
so repeated failures no longer appear as “Live”.

Comment thread apps/telemetry/app/pages/index.vue Outdated
Comment thread apps/telemetry/app/utils/telemetry-icons.ts
Comment on lines +1 to +5
{
"id": "e46d3faa-6409-4729-a210-71f2b864ab6b",
"prevId": "4951be6d-5aa0-4026-b064-67cdc0a6ebfe",
"version": "7",
"dialect": "postgresql",

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

Remove generated Drizzle migration metadata from this PR. Both artifacts violate the repository rule against committing generated files.

  • apps/telemetry/server/db/migrations/postgresql/meta/0001_snapshot.json#L1-L5: remove the generated snapshot artifact.
  • apps/telemetry/server/db/migrations/postgresql/meta/_journal.json#L11-L17: remove the generated journal entry.

As per coding guidelines, “Do not commit secrets, .env files, API keys, generated files, or modifications to node_modules/.”

📍 Affects 2 files
  • apps/telemetry/server/db/migrations/postgresql/meta/0001_snapshot.json#L1-L5 (this comment)
  • apps/telemetry/server/db/migrations/postgresql/meta/_journal.json#L11-L17
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/telemetry/server/db/migrations/postgresql/meta/0001_snapshot.json`
around lines 1 - 5, Remove the generated Drizzle migration metadata artifacts:
delete the snapshot file at
apps/telemetry/server/db/migrations/postgresql/meta/0001_snapshot.json and
remove the corresponding journal entry at
apps/telemetry/server/db/migrations/postgresql/meta/_journal.json lines 11-17.

Source: Coding guidelines

Comment thread apps/telemetry/shared/types/telemetry.ts
HugoRCD added 2 commits July 24, 2026 00:01
The Nucleo "glass" display icons ship a single fixed dark gradient with
no currentColor hook, so they read as an unexplained dark blob floating
on a light card. Frame them in an elevated GlassIconTile instead so the
surface (not the icon) adapts to the theme.

Chart bar/donut colors were also darkened toward black unconditionally,
tuned only for the near-black dark mode background — they now use
theme-aware --chart-* tokens that stay full-saturation on light cards.
- useFreshIds: bound seenIds to the current visible row set instead of
  accumulating every id ever seen for the life of the page
- useLiveRefresh: surface a lastError so a repeatedly failing poll no
  longer shows as "Live" — LiveIndicator now reads "Reconnecting"
- drop an HTML comment from index.vue's template (project convention)
- add missing JSDoc on providerIcon, osLabel, ErrorCodeStat, DurationStats

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@apps/telemetry/app/pages/index.vue`:
- Line 217: Update the LiveIndicator binding in the dashboard page to mark the
indicator as errored when liveError or any useFetch error ref (statsError,
runsError, or feedError) is present. Preserve the existing liveActive state and
last-event timestamp behavior while combining all relevant errors for the
has-error prop.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 5e1ebb99-a261-4736-9ee1-a03e0fae79ac

📥 Commits

Reviewing files that changed from the base of the PR and between 078a245 and d6f942e.

📒 Files selected for processing (19)
  • apps/telemetry/app/assets/css/main.css
  • apps/telemetry/app/components/AgentsBreakdown.vue
  • apps/telemetry/app/components/CiBreakdown.vue
  • apps/telemetry/app/components/CommandsTable.vue
  • apps/telemetry/app/components/DailyActivityChart.vue
  • apps/telemetry/app/components/DurationHistogram.vue
  • apps/telemetry/app/components/EnvironmentBreakdown.vue
  • apps/telemetry/app/components/ErrorCodesCard.vue
  • apps/telemetry/app/components/GlassIconTile.vue
  • apps/telemetry/app/components/LiveFeed.vue
  • apps/telemetry/app/components/LiveIndicator.vue
  • apps/telemetry/app/components/StatCard.vue
  • apps/telemetry/app/components/VersionsCard.vue
  • apps/telemetry/app/composables/useFreshIds.ts
  • apps/telemetry/app/composables/useLiveRefresh.ts
  • apps/telemetry/app/pages/index.vue
  • apps/telemetry/app/pages/login.vue
  • apps/telemetry/app/utils/telemetry-icons.ts
  • apps/telemetry/shared/types/telemetry.ts

</h1>

<div class="flex flex-wrap items-center gap-2">
<LiveIndicator :live="liveActive" :has-error="!!liveError" :last-event-at="stats?.lastEventAt ?? null" @toggle="toggleLive" />

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🌐 Web query:

For Nuxt 4.5, does useFetch expose initial and watched request failures through its error ref without throwing from await useFetch?

💡 Result:

In Nuxt 4.5, useFetch does not throw when a request fails, regardless of whether you await the composable or not [1][2]. Instead, it captures errors into the returned error ref, and you must check this ref to handle failures [1][3][4]. Key points regarding this behavior: 1. No Rejection: The promise returned by useFetch (and its internal refresh/execute functions) does not reject on network or HTTP errors [2][4]. 2. Error Ref: When a fetch fails, the error ref provided by the composable is populated with the error object [1][3][5]. 3. Handling Errors: Because it does not throw, wrapping await useFetch in a try/catch block will not catch request errors [2][4]. You must instead monitor the error state, for example by checking if error.value is truthy [2][4]. 4. Consistent Behavior: This behavior is intentional to maintain the reactive state (data, pending, status, error) provided by the composable [2]. While there have been community discussions and feature requests to add an optional throwOnError configuration, it remains non-throwing in the core Nuxt implementation [2][4]. Note that this behavior is specific to the Nuxt composable. It is distinct from the VueUse useFetch implementation, which provides an execute(true) parameter that can cause the promise to reject if the request fails [6][7].

Citations:


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== locate files =="
fd -a 'index\.vue$|LiveIndicator\.vue$' . | sed 's#^\./##' | head -100

echo
echo "== outline index.vue =="
ast-grep outline apps/telemetry/app/pages/index.vue --view compact || true

echo
echo "== relevant index.vue sections =="
sed -n '1,260p' apps/telemetry/app/pages/index.vue | nl -ba

echo
echo "== LiveIndicator files =="
files=$(fd 'LiveIndicator\.vue$' .)
printf '%s\n' "$files" | while read -r f; do
  echo "--- $f ---"
  wc -l "$f"
  sed -n '1,260p' "$f" | nl -ba
done

Repository: HugoRCD/evlog

Length of output: 2008


🏁 Script executed:

#!/bin/bash
set -euxo pipefail

echo "== pwd =="
pwd

echo "== locate files =="
fd 'index\.vue$|LiveIndicator\.vue$' . || true

echo
echo "== files matching telemetry index =="
fd 'index\.vue$' . | sed -n '/apps\/telemetry\/app\/pages\/index.vue/p'

echo
echo "== relevant index.vue sections =="
if [ -f apps/telemetry/app/pages/index.vue ]; then
  sed -n '1,280p' apps/telemetry/app/pages/index.vue | nl -ba
fi

echo
echo "== LiveIndicator files =="
fd 'LiveIndicator\.vue$' . | while read -r f; do
  echo "--- $f ---"
  wc -l "$f"
  sed -n '1,260p' "$f" | nl -ba
done

Repository: HugoRCD/evlog

Length of output: 2008


🏁 Script executed:

#!/bin/bash
set -euxo pipefail

echo "== pwd =="
pwd

echo "== top-level =="
git ls-files | sed -n '1,80p'

echo
echo "== locate telemetry index =="
git ls-files | grep -E '^apps/telemetry/app/pages/index\.vue$' || true

echo
echo
echo "== index.vue lines =="
if git ls-files | grep -Eq '^apps/telemetry/app/pages/index\.vue$'; then
  git show "HEAD:apps/telemetry/app/pages/index.vue" | sed -n '1,280p' | nl -ba
fi

echo
echo "== locate LiveIndicator =="
git ls-files | grep 'LiveIndicator\.vue$' || true

echo
echo "== LiveIndicator content =="
git ls-files | grep 'LiveIndicator\.vue$' | while read -r f; do
  echo "--- $f ---"
  git show "HEAD:$f" | sed -n '1,260p' | nl -ba
done

Repository: HugoRCD/evlog

Length of output: 2008


Include fetch errors in the reconnecting state.

LiveIndicator receives only liveError, but Nuxt’s useFetch captures failed initial/watched requests in the returned error ref instead of throwing. A failure in statsError, runsError, or feedError can make the dashboard show “Live” even when that data failed to load.

Proposed fix
-        <LiveIndicator :live="liveActive" :has-error="!!liveError" :last-event-at="stats?.lastEventAt ?? null" `@toggle`="toggleLive" />
+        <LiveIndicator :live="liveActive" :has-error="!!(liveError || statsError || runsError || feedError)" :last-event-at="stats?.lastEventAt ?? null" `@toggle`="toggleLive" />
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<LiveIndicator :live="liveActive" :has-error="!!liveError" :last-event-at="stats?.lastEventAt ?? null" @toggle="toggleLive" />
<LiveIndicator :live="liveActive" :has-error="!!(liveError || statsError || runsError || feedError)" :last-event-at="stats?.lastEventAt ?? null" `@toggle`="toggleLive" />
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/telemetry/app/pages/index.vue` at line 217, Update the LiveIndicator
binding in the dashboard page to mark the indicator as errored when liveError or
any useFetch error ref (statsError, runsError, or feedError) is present.
Preserve the existing liveActive state and last-event timestamp behavior while
combining all relevant errors for the has-error prop.

@HugoRCD
HugoRCD merged commit 8f4839d into main Jul 24, 2026
17 of 18 checks passed
@HugoRCD HugoRCD self-assigned this Jul 24, 2026
@HugoRCD
HugoRCD deleted the feat/telemetry-live-dashboard branch July 24, 2026 07:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant